﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.WebControls;
using Microsoft.SharePoint;

namespace Xodeuz.SP.Common
{
    public class ListReflector<T> where T : new()
    {
        public List<T> Items { get; set; }
        public String ListName { get; set; }
        private SPList _list;
        public SPContext Context;
        private readonly Type _type;
        private readonly SPWeb _web;

        private ListReflector()
        {
            Items = _list.GetItems<T>(new SPQuery { Query = "<Where><IsNotNull><FieldRef Name='ID' /></IsNotNull></Where>" });
        }

        private ListReflector(Type type)
        {
            Items = new List<T>();
            GetList(type);
            CreateRelatedFields(type);
        }

        public ListReflector(Type type, SPWeb web)
        {
            _type = type;
            _web = web;

            Items = new List<T>();
            GetList(type);
        }

        private void CreateRelatedFields(Type type)
        {
            var fields = ReflectionService.GetFieldCreations(type);

            if (_list != null)
            {
                foreach (var key in fields.Keys)
                {
                    if (ReadOnly.CreationFields.Contains(fields[key].InternalName)) continue;
                    String field = _list.Fields.Add(fields[key].InternalName, fields[key].Type, false);

                    if (!String.IsNullOrEmpty(fields[key].DisplayName))
                    {
                        var newField = _list.Fields.GetFieldByInternalName(field);
                        newField.Title = fields[key].DisplayName;
                        newField.Update();
                    }
                }
                _list.Update();
            }
        }

        public static ListReflector<T> GetList<T>(String listName) where T : new()
        {
            return new ListReflector<T>();
        }

        public static ListReflector<T> CreateList<T>() where T : new()
        {
            var type = typeof (T);
            return new ListReflector<T>(type);
        }

        public static ListReflector<T> CreateList<T>(SPWeb web) where T : new()
        {
            var type = typeof(T);
            return new ListReflector<T>(type, web);
        }


        private void GetList(Type type)
        {
            if (type == null) throw new ArgumentNullException("type");

            if (HttpContext.Current != null && Context == null)
                Context = SPContext.GetContext(HttpContext.Current);

            if (Context == null && _web != null)
                Context = SPContext.GetContext(_web);

            var attribute = (SharePointList)ReflectionService.GetListCreationInformation(type);
            if (attribute != null)
            {
                _list = Context.Web.Lists.TryGetList(attribute.Name);

                if (_list != null)
                    return;

                attribute.EnsureList();
                _list = Context.Web.Lists.TryGetList(attribute.Name);

                var contentTypes = ReflectionService.GetContentTypes(_type);

                var enumerable = contentTypes as ContentType[] ?? contentTypes.ToArray();
                if (enumerable.Length != 0)
                {
                    enumerable.ForEach(AddContentTypeToList);
                    _list.Update();
                }
                else
                {
                    this.CreateRelatedFields(attribute.ItemModel);
                }
               
            }
        }

        private void AddContentTypeToList(ContentType ct)
        {
            if (!_list.ContentTypesEnabled)
            {
                _list.ContentTypesEnabled = true;
                _list.Update();
            }

            SPContentTypeId ctId = new SPContentTypeId(ct.Id);
            SPContentType contentType = Context.Web.ContentTypes[ctId] ?? Context.Site.RootWeb.ContentTypes[ctId];

            if (_list.ContentTypes[ctId] == null && contentType != null)
            {
                _list.ContentTypes.Add(contentType);
            }
        }
    }
}
